#ifndef Symbol_First
#define Symbol_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Object.h"

//---- SymbolTable -------------------------------------------------------------

class SymbolTable: public Object {
public:
	MetaDef(SymbolTable);
	SymbolTable(int cap= 200);
	~SymbolTable();
	const char *Lookup(const char *name);
	const char *MakeId(const char *name);
protected:
	void Expand();
	int GetSlot(const char *s);
private:
	char **table;
	int capacity, size;
};

inline const char *SymbolTable::Lookup(const char *s)
	{ return table[GetSlot(s)]; }

//---- Symbol ------------------------------------------------------------------

class Symbol {
public:
	Symbol();
	Symbol(const char *name);
	Symbol(const Symbol &at);

	void operator=(const Symbol &at);
	u_int Id() const;
	const char *AsString() const;

	friend bool operator== (const Symbol&, const Symbol&);
	friend bool operator!= (const Symbol&, const Symbol&);

	OStream &PrintOn(OStream&) const;
	IStream &ReadFrom(IStream&);

	friend OStream& operator<< (OStream&, const Symbol&);
	friend IStream& operator>> (IStream&, Symbol&);

	static SymbolTable *SymTab;
	static const char *MakeId(const char *s);
	static const char *Lookup(const char *s);

private:	
	const char *id;
};

SimpleMetaDef(Symbol);

inline Symbol::Symbol()
	{ id= 0; }
inline Symbol::Symbol(const char *name)
	{ id= MakeId(name); }
inline Symbol::Symbol(const Symbol &at)
	{ id= at.id; }
inline void Symbol::operator=(const Symbol &at)
	{ id= at.id; }
inline u_int Symbol::Id() const
	{ return (u_int) id; }
inline const char *Symbol::AsString() const
	{ return id; }
inline const char *Symbol::Lookup(const char *s)
	{ return SymTab ? SymTab->Lookup(s) : 0; }
inline bool operator== (const Symbol &a1, const Symbol &a2)
	{ return (bool) (a1.id == a2.id); }
inline bool operator!= (const Symbol &a1, const Symbol &a2)
	{ return (bool) (a1.id != a2.id); }
inline OStream& operator<< (OStream &s, const Symbol &a)
	{ return a.PrintOn(s); }
inline IStream& operator>> (IStream &s, Symbol &a)
	{ return a.ReadFrom(s); }

#endif
